package com.luoye.lj.util.excel;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class ExcelReadUtil<T> {

    public List<Map<String,String>> readExcel(InputStream is,String[] ifList,String extendName){
        List<Map<String,String>> resultList;
        if (extendName.endsWith(".xls")) {
            resultList=readExcel2003(is,ifList);
        } else {
            resultList = readExcel2007(is,ifList);
        }
        log.info("resultList->"+resultList);
        return resultList;
    }
    public List<T> readExcel(InputStream is,String[] ifList,String extendName,Class<T> clazz) throws IllegalAccessException, InstantiationException{
        List<T> entityList=new ArrayList<>();

        //先读取数据
        List<Map<String,String>> resultList;
        if (extendName.endsWith(".xls")) {
            resultList=readExcel2003(is,ifList);
        } else {
            resultList = readExcel2007(is,ifList);
        }
        log.info("resultList->"+resultList);

        for(Map<String,String> rs:resultList) {
            T object = clazz.newInstance();
            entityList.add(object);
            setFields(clazz, rs, object);
        }

        return entityList;
    }

    public boolean setFields(Class<T> clazz, Map<String, String> rs, T object) throws IllegalAccessException {
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field sField : declaredFields) {
            String mapValue =rs.get(sField.getName());
            if(mapValue==null){
                continue;
            }
            sField.setAccessible(true);
            Class sFieldType=sField.getType();
            String sFieldTypeName=sField.getType().getSimpleName();
            if(sFieldType.isPrimitive()){//基本数据类型
                if ("int".equals(sFieldTypeName)) {
                    try {
                        int value= Integer.parseInt(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("long".equals(sFieldTypeName)) {
                    try {
                        long value= Long.parseLong(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("float".equals(sFieldTypeName)) {
                    try {
                        float value= Float.parseFloat(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("double".equals(sFieldTypeName)) {
                    try {
                        double value= Double.parseDouble(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("char".equals(sFieldTypeName)) {
                    try {
                        char value=(char) Integer.parseInt(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("byte".equals(sFieldTypeName)) {
                    try {
                        byte value= Byte.parseByte(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("short".equals(sFieldTypeName)) {
                    try {
                        short value= Short.parseShort(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                }
                else if ("boolean".equals(sFieldTypeName)) {
                    try {
                        boolean value= Boolean.parseBoolean(mapValue);
                        sField.set(object,value);
                    }catch (NumberFormatException ex){
                        //ex.printStackTrace();
                        return false;
                    }
                }
            }else {
                if ("Date".equals(sFieldTypeName)) {
                    SimpleDateFormat sdtf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    try {
                        Date value = sdtf.parse(mapValue);
                        sField.set(object, value);
                    } catch (ParseException ex) {
                        //ex.printStackTrace();
                        return false;
                    }
                } else if ("String".equals(sFieldTypeName)) {
                    String value = mapValue;
                    sField.set(object, value);
                } else {
                    if (mapValue != null && !"null".equals(mapValue)) {
                        Object objInstance = null;
                        try {
                            objInstance = sFieldType.newInstance();
                        } catch (InstantiationException e) {
                            //ex.printStackTrace();
                            return false;
                        }
                        sField.set(object, objInstance);
                    }
                }
            }
        }
        return true;
    }

    public List<Map<String,String>> readExcel2007(InputStream is,String[] ifList) {
        List<Map<String,String>> rowList = new ArrayList<>();
        try {
            XSSFWorkbook wb = new XSSFWorkbook(is);
            XSSFSheet sheet = wb.getSheetAt(0);
            rowList = readExcelPractical(sheet,ifList);
        } catch (IOException e) {
            log.error("exception",e);
        }
        return rowList;
    }

    public List<Map<String,String>> readExcel2003(InputStream is,String[] ifList) {
        List<Map<String,String>> rowList = new ArrayList<>();
        try {
            HSSFWorkbook wb = new HSSFWorkbook(is);
            HSSFSheet sheet = wb.getSheetAt(0);
            rowList = readExcelPractical(sheet,ifList);
        } catch (IOException e) {
            log.error("exception",e);
        }
        return rowList;
    }
    private List<Map<String,String>> readExcelPractical(Sheet sheet, String[] ifList) {
        List<Map<String,String>> rowList = new ArrayList<>();
        try {
            //DecimalFormat df = new DecimalFormat("#");
            int lastRowIndex = sheet.getLastRowNum(); // 末尾
            //不读取第一行的内容
            for (int rIndex = 1; rIndex <= lastRowIndex; rIndex++) {
                Row row = sheet.getRow(rIndex);
                if (row == null) {
                    //当读取行为空时
                    continue;
                }
                Map<String,String> colMap = new HashMap<String,String>();
                int lastCellIndex=row.getLastCellNum();
                for(int ci=0;ci<=lastCellIndex&&ci<ifList.length;ci++){
                    Cell cell =row.getCell(ci);
                    if(cell!=null){
                        String v=cell.getStringCellValue();
                        colMap.put(ifList[ci],v);
                    }
                }
                //end for j
                rowList.add(colMap);
            }//end for i
        } catch (Exception e) {
            log.error("exception",e);
        }
        return rowList;
    }
}